﻿
Imports System.Threading
Imports osi.root.constants
Imports osi.root.connector
Imports osi.root.delegates
Imports osi.root.envs

Namespace atomic
    Public Module _atomic
        Private ReadOnly x86 As Boolean = False
        Private ReadOnly amd64 As Boolean = False

        Sub New()
            x86 = x32_cpu
            amd64 = x64_cpu
        End Sub

        Public Sub eva(ByRef i As Double, ByVal j As Double)
            'based on atomTests.doubleAtomTest, double is using FPU, so it's safe to use VolatileWrite
            If x86 OrElse amd64 Then
                Thread.VolatileWrite(i, j)
            Else
                Interlocked.Exchange(i, j)
            End If
        End Sub

        Public Sub eva(ByRef i As Int32, ByVal j As Int32)
            If x86 OrElse amd64 Then
                Thread.VolatileWrite(i, j)
            Else
                Interlocked.Exchange(i, j)
            End If
        End Sub

        Public Sub eva(ByRef i As Int64, ByVal j As Int64)
            If amd64 Then
                Thread.VolatileWrite(i, j)
            Else
                Interlocked.Exchange(i, j)
            End If
        End Sub

        Public Sub eva(ByRef i As IntPtr, ByVal j As IntPtr)
            Thread.VolatileWrite(i, j)
        End Sub

        Public Sub eva(ByRef i As Object, ByVal j As Object)
            Interlocked.Exchange(i, j)
        End Sub

        Public Sub eva(ByRef i As Single, ByVal j As Single)
            If x86 OrElse amd64 Then
                Thread.VolatileWrite(i, j)
            Else
                Interlocked.Exchange(i, j)
            End If
        End Sub

        Public Function read(ByRef i As Int64) As Int64
            If amd64 Then
                Return Thread.VolatileRead(i)
            Else
                Return Interlocked.Read(i)
            End If
        End Function

        Public Function read(ByRef i As Int32) As Int32
            'no support in .net framework for cpu <32 bit
            Return Thread.VolatileRead(i)
        End Function

        Public Function read(ByRef i As Double) As Double
            Return Thread.VolatileRead(i)
        End Function

        Public Function read(ByRef i As Object) As Object
            'no support in .net framework for cpu <32 bit
            Return Thread.VolatileRead(i)
        End Function

        Public Function read(Of T As Class)(ByRef i As T) As T
            'no support in .net framework for cpu <32 bit
            Return Thread.VolatileRead(i)
        End Function

        Public Function compare_exchange(ByRef i As Int32, ByVal v As Int32, ByVal cmp As Int32) As Boolean
            If i = cmp Then
                Return Interlocked.CompareExchange(i, v, cmp) = cmp
            Else
                Return False
            End If
        End Function

        Public Sub create_if_nothing(Of T As Class)(ByRef i As T, ByVal ctor As _do(Of T))
            If i Is Nothing Then
                Interlocked.CompareExchange(i, ctor(), Nothing)
                k_assert(Not i Is Nothing)
            End If
        End Sub

        Public Sub create_if_nothing(Of T As {Class, New})(ByRef i As T)
            If i Is Nothing Then
                create_if_nothing(i, Function() New T())
            End If
        End Sub
    End Module
End Namespace
